package menu

import (
	"context"
	"database/sql"
	"go-zero-project/common/excption"
	"go-zero-project/services/user/rpc/constans"
	"go-zero-project/services/user/rpc/internal/mapper"
	"go-zero-project/services/user/rpc/internal/mapper/bo"
	"go-zero-project/services/user/rpc/internal/mapper/entity"

	"go-zero-project/services/user/rpc/internal/svc"
	"go-zero-project/services/user/rpc/pb"

	"github.com/zeromicro/go-zero/core/logx"
)

type SaveMenuLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewSaveMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveMenuLogic {
	return &SaveMenuLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *SaveMenuLogic) SaveMenu(in *pb.SaveMenuReq) (*pb.SaveMenuResp, error) {
	// 1.菜单非法性校验
	menuMapper := mapper.NewMenuMapper()
	checkErr := l.checkMenu(in, menuMapper)
	if checkErr != nil {
		return nil, checkErr
	}
	// 2.保存DB
	menuEntity := entity.SysMenuEntity{
		ParentId: sql.NullInt64{Int64: in.ParentId, Valid: true}, Name: in.Name, Url: in.Url,
		Perms: in.Perms, Type: sql.NullInt16{Int16: int16(in.MenuType), Valid: true}, Icon: in.Icon,
		OrderNum: sql.NullInt32{Int32: in.OrderNum, Valid: true},
	}
	err := menuMapper.SaveMenu(l.svcCtx.DBEngin, &menuEntity)
	if err != nil {
		return nil, err
	}
	// 3.返回参数
	return &pb.SaveMenuResp{MenuId: menuEntity.MenuId}, nil
}

func (l *SaveMenuLogic) checkMenu(in *pb.SaveMenuReq, menuMapper *mapper.MenuMapper) error {
	// 1.1 查询是否重复
	menuBO := bo.SysMenuBO{ParentId: in.ParentId, Name: in.Name}
	selectCount, err := menuMapper.SelectCount(l.svcCtx.DBEngin, menuBO)
	if err != nil {
		return err
	}
	if selectCount > 0 {
		return excption.NewErrCode(constans.MenuNameRepeatError)
	}
	err2 := l.doCheckMenu(in, menuMapper)
	if err2 != nil {
		return err2
	}
	return nil
}

func (l *SaveMenuLogic) doCheckMenu(in *pb.SaveMenuReq, menuMapper *mapper.MenuMapper) error {
	// 如果是菜单 则Url不能为空
	if in.MenuType == 1 {
		url := in.Url
		if len(url) < 1 {
			return excption.NewErrCode(constans.MenuUrNotEmptyError)
		}
		menuBO := bo.SysMenuBO{Url: url, NoType: false, Type: 2}
		selectUrlCount, selectPermsCountErr := menuMapper.SelectCount(l.svcCtx.DBEngin, menuBO)
		if selectPermsCountErr != nil {
			return selectPermsCountErr
		}
		if selectUrlCount > 0 {
			return excption.NewErrCode(constans.MenuUrlRepeatError)
		}
	}
	// 查询上级菜单
	menuBO := bo.SysMenuBO{MenuId: in.ParentId, NoType: true}
	parentSysMenu, parentSysMenuErr := menuMapper.SelectOne(l.svcCtx.DBEngin, menuBO)
	if parentSysMenuErr != nil {
		return parentSysMenuErr
	}
	if parentSysMenu.MenuId < 1 {
		return excption.NewErrCode(constans.ParentMenuNotExistError)
	}
	// 如果是 目录、菜单
	if in.MenuType == 0 || in.MenuType == 1 {
		if parentSysMenu.Type.Int16 != 0 {
			return excption.NewErrCode(constans.ParentTypeOnlyCatalogError)
		}
	}
	// 如果是按钮 perms 必须唯一
	if in.MenuType == 2 {
		perms := in.Perms
		if len(perms) < 1 {
			return excption.NewErrCode(constans.MenuPermsNotEmptyError)
		}
		menuBO = bo.SysMenuBO{Perms: perms, NoType: false, Type: 2}
		selectPermsCount, selectPermsCountErr := menuMapper.SelectCount(l.svcCtx.DBEngin, menuBO)
		if selectPermsCountErr != nil {
			return selectPermsCountErr
		}
		if selectPermsCount > 0 {
			return excption.NewErrCode(constans.PermsRepeatError)
		}
		// 上级只能是菜单类型
		if parentSysMenu.Type.Int16 != 1 {
			return excption.NewErrCode(constans.ParentTypeOnlyMenuError)
		}
	}
	return nil
}
